import os,re

LOOP_TIMER_PAT = re.compile(r"Laya.timer.loop\(\s*[0-9]+\s*,\s*this\s*,\s*[a-zA-Z]+\s*.\s*([_a-zA-Z0-9]+)\)");
ONCE_TIMER_PAT = re.compile(r"Laya.timer.once\(\s*[0-9]+\s*,\s*this\s*,\s*[a-zA-Z]+\s*.\s*([_a-zA-Z0-9]+)\)");
FRAME_ONCE_TIMER_PAT = re.compile(r"Laya.timer.frameOnce\(\s*[0-9]+\s*,\s*this\s*,\s*[a-zA-Z]+\s*.\s*([_a-zA-Z0-9]+)\)");
FRAME_LOOP_TIMER_PAT = re.compile(r"Laya.timer.frameLoop\(\s*[0-9]+\s*,\s*this\s*,\s*[a-zA-Z]+\s*.\s*([_a-zA-Z0-9]+)\)");
INVOKE_FUN_PAT = re.compile(r"this\s*\.\s*([_0-9a-zA-Z]+)\(.*?\)",re.DOTALL);

CLEAR_PAT_DICT = {}
FUNC_PAT_DICT = {}

def isIgnore(filePath:str,content)->bool:
    if filePath and filePath.find(".d.ts")>-1:
        return True
    if isNotModuleOrManager(filePath):
        return True
    return isConfig(filePath) or isTargetClass("Controller",content) or isTargetClass("BaseCache",content) or isTargetClass("UIModel3DBase",content)

def isTargetClass(baseName:str,content:str)->bool:
    pattern = re.compile(r"class\s+[_a-zA-Z]+?\s+extends\s+"+baseName)
    ret=pattern.search(content)
    return ret!=None

def isNotModuleOrManager(filePath):
    tt = os.path.split(filePath)
    dirPath=str(tt[0]).lower()
    fileName=str(tt[1]).lower()
    return dirPath.find("module")==-1 or fileName.find("manager") > -1

def isConfig(filePath)->bool:
    ret = True
    if filePath!=None and isinstance(filePath,str) and os.path.isfile(filePath):
        folder = os.path.split(filePath)[0]
        folders = folder.split("/")
        if not folders or len(folders)==1:
            folders = folder.split(os.path.sep)
        ret = folders[-1] =="configs"
    return ret

def getTimerFuncs(contentStr:str)->list[str]:
    timerFuncs = []
    timerFuncs.extend(LOOP_TIMER_PAT.findall(contentStr))
    timerFuncs.extend(ONCE_TIMER_PAT.findall(contentStr))
    timerFuncs.extend(FRAME_ONCE_TIMER_PAT.findall(contentStr))
    timerFuncs.extend(FRAME_LOOP_TIMER_PAT.findall(contentStr))
    return timerFuncs;

def getClearFnPat(fn):
    empty="empty"
    pat = CLEAR_PAT_DICT.get(fn,empty)
    if pat == empty:
        pat = re.compile(r"Laya.timer.clear\(\s*this\s*,\s*[a-zA-Z]+\s*.\s*"+fn+r"\)");
        CLEAR_PAT_DICT[fn] = pat
        
    return pat

def getPatByFuncName(funcName):
    empty="empty"
    pat = FUNC_PAT_DICT.get(funcName,empty)
    if pat == empty:
        # pat = re.compile(r" *?[a-zA-Z]+\s+?"+funcName+r"\(\)\:.*?\{.*\}",re.DOTALL); 
        pat = re.compile(r" *?[a-zA-Z]*\s*?[^.a-zA-Z0-9]"+funcName+r"\(.*?\).*?\{.*\}",re.DOTALL);  #兼容函数后面没有写返回值的函数体,函数名前面没有写修饰符
        FUNC_PAT_DICT[funcName] = pat
        
    return pat

#
def findInvokeFuns(fnStr):
    p = INVOKE_FUN_PAT
    funNames = p.findall(fnStr)
    return funNames;

def subFunc(fnStr:str,fnName:str):
    idx = fnStr.find(fnName)
    idx2 = -1
    minIdx = -1
    retFuncStr = fnStr
    modifiers=["public","protected","private"]
    for item in modifiers:
        idx2 = fnStr.find(item,idx)
        if idx2 > -1 and ( minIdx==-1 or (minIdx>-1 and idx2<minIdx)):
            minIdx = idx2
            retFuncStr = fnStr[:idx2]
    return retFuncStr;

def readDirFiles(dirPath:str)->list[str]:
    files = [];
    if os.path.isdir(dirPath) and os.path.exists(dirPath):
        temps = os.listdir(dirPath);
        for f in temps:
            realPath = os.path.join(dirPath,f)
            isFile = os.path.isfile(realPath)
            ext = os.path.splitext(realPath)[1]
            if isFile and ext==".ts":
                files.append(realPath)
            if os.path.isdir(realPath):
                files.extend(readDirFiles(realPath))
    return files;